#include <iostream>
#include "login.h"
#include "functions.h"
#include "globals.h"

using std::cout;
using std::cin;

Login::Login()
{
    //cout << "Unnamed RPG -- development version\r\n\r\n";
    //myName = "";
    //myPass = "";

    processing = false;
    accountID = 0;
}

Login::~Login()
{

}

void Login::wait_response()
{
    processing = true;

    while (processing)
    {
        net.receive_data();

	    SDL_Delay(100);
    }
}

int Login::get_number(int min, int max)
{
    int num = 0;
    std::string input = "";

    while (true)
    {
        getline(cin, input);
        std::stringstream stream(input);
        if (stream >> num)
            if ((num >= min && num <= max) || num == 9) return num;

        cout << "Invalid value\r\n";
    }
}

void Login::account_menu(int num)
{
    std::string username;
    std::string password;
    static unsigned char pass_hash[65];

    processing = true;

    if (num == 0)
    {
        cout << "\r\n"
             << "1. Create account\r\n"
             << "2. Login\r\n\r\n";

        num = get_number(1, 2);
    }

    switch (num)
    {
        case 1:
            //cout << "\r\nCreate account\r\n\r\n";
            cout << "\r\n Username: ";
            getline(cin, username);
            cout << " Password: ";
            getline(cin, password);

            sha256(password.c_str(), pass_hash);

            cout << "\r\nCreating account...\r\n";
            create_account(username, std::string(pass_hash));

            break;
        case 2:
            //cout << "\r\nLogin\r\n\r\n";
            cout << "\r\n Username: ";
            getline(cin, username);
            cout << " Password: ";
            getline(cin, password);

            sha256(password.c_str(), pass_hash);

            cout << "\r\nLogging in...\r\n";
            log_in(username, std::string(pass_hash));

            break;
    }

    //myName = username;
    //myPass = password;

    wait_response();
}

void Login::character_menu()
{
    int num = 0;
    //int character;
    std::string charname = "";

    get_characters();

    int i = 0;

    while (i < 10)
    {
        net.receive_data();

        SDL_Delay(100);
        i++;
    }

        /*while (characters.size() < numCharacters) {
            net.receive_data();

            SDL_Delay(100);
            //output.write("asd");
        }*/

    for (int i = 0; i < characters.size(); i++) {
        cout << i + 1 << ": " << characters[i].name << "    CLASS: " << characters[i].type << " LEVEL: " << characters[i].level << "\r\n";
    }

    for (int i = characters.size(); i < 8; i++) {
        cout << i + 1 << ": empty" << "\r\n";
    }

    cout << "\r\n"
         << "Select character or type 9 to create new character\r\n\r\n";

    num = get_number(1, characters.size());

    switch (num)
    {
        case 9:
            cout << " Name: ";
            getline(cin, charname);

            create_character(charname);
            wait_response();
            break;

        default:
            //character c = characters.at(num);      // vector::at throws an out-of-range
            cout << "You chose character number " << num << "\r\n";

            P.set_name(characters[num - 1].name);
            P.set_x(128);
            P.set_y(128);
            P.set_camera();

            RakNet::BitStream bsOut;
            bsOut.Write((RakNet::MessageID)ID_PLAYER_JOIN);
            bsOut.Write(characters[num - 1].id);
            net.send_message(&bsOut, MEDIUM_PRIORITY, RELIABLE_ORDERED);
            break;
    }
}

void Login::addCharacter(int id, std::string name, int type, int level)
{
    character c;
    c.id = id;
    c.name = name;
    c.type = type;
    c.level = level;
    characters.push_back(c);
}

void Login::stopProcessing()
{
    processing = false;
}

void Login::setAccountID(int accountID)
{
    this->accountID = accountID;
}

int Login::getAccountID()
{
    return accountID;
}

void Login::create_account(std::string name, std::string pass)
{
    RakNet::BitStream bsOut;

    bsOut.Write((RakNet::MessageID)ID_ACCOUNT_CREATE);
    bsOut.Write(name.c_str());
    bsOut.Write(pass.c_str());

    net.send_message(&bsOut, MEDIUM_PRIORITY, RELIABLE);
}

void Login::log_in(std::string name, std::string pass)
{
    RakNet::BitStream bsOut;

    bsOut.Write((RakNet::MessageID)ID_ACCOUNT_LOGIN);
    bsOut.Write(name.c_str());
    bsOut.Write(pass.c_str());

    net.send_message(&bsOut, MEDIUM_PRIORITY, RELIABLE);
}

void Login::create_character(std::string name)
{
    RakNet::BitStream bsOut;

    bsOut.Write((RakNet::MessageID)ID_CHARACTER_CREATE);
    bsOut.Write(accountID);
    bsOut.Write(name.c_str());

    net.send_message(&bsOut, MEDIUM_PRIORITY, RELIABLE);
}

void Login::get_characters()
{
    RakNet::BitStream bsOut;

    bsOut.Write((RakNet::MessageID)ID_CHARACTER_INFO);
    bsOut.Write(accountID);

    net.send_message(&bsOut, MEDIUM_PRIORITY, RELIABLE);

    characters.clear();
}
